package com.tianzhu.config;


import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.RememberMeAuthenticationProvider;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.AnonymousAuthenticationFilter;
import org.springframework.security.web.context.SecurityContextPersistenceFilter;

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
	
	static final String REMEMBER_ME_KEY = "78780c25-1849-4796-a79c-0f4326f32dfd";

	@Autowired
    UserDetailsService userDetailService;

	@Override
	@Autowired
	protected void configure(AuthenticationManagerBuilder auth)
			throws Exception {
		auth.authenticationProvider(customAuthenticationProvider());
	}

	@Override
	public void configure(WebSecurity web) throws Exception {
		web.expressionHandler(webSecurityExpressionHandler())
					.ignoring().antMatchers("/static/**");
					   /*.antMatchers("/home")
					   .antMatchers("/");*/
	}

	@Override
	protected void configure(HttpSecurity http) throws Exception {
		http
		
		.authorizeRequests()
        .expressionHandler(webSecurityExpressionHandler())
        .antMatchers("/database/**").access("hasRole('ROLE_DEVELOPER')")
        .antMatchers("/admin/**").access("hasRole('ROLE_ADMIN')")
        .antMatchers("/customer/**").access("hasRole('ROLE_USER')")
        .and()
        .formLogin()
            .loginPage("/login")
            .usernameParameter("username")
            .passwordParameter("password")
            .loginProcessingUrl("/login")
            .failureUrl("/login?error")
            .defaultSuccessUrl("/")
            .and()
        .logout()
            .logoutUrl("/logout")
            .logoutSuccessUrl("/login?logout")
            .invalidateHttpSession(true)
            .and()
        .rememberMe()
            .tokenRepository(springDataTokenRepository())
            .useSecureCookie(true)
             .and()
            .anonymous().disable()
            .addFilterBefore(anonymousAuthenticationFilter(), AnonymousAuthenticationFilter.class)
            .addFilterAfter(mdcUsernameInsertingFilter(), SecurityContextPersistenceFilter.class)
        .exceptionHandling()
            .accessDeniedPage("/accessdenied")
            .and().httpBasic();
	}
	
		
	@Bean
    public PasswordEncoder passwordEncoder() {
        BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
        return passwordEncoder;
    }
    
    @Bean
    public CustomAuthenticationProvider customAuthenticationProvider() {
    	CustomAuthenticationProvider customAuthenticationProvider = new CustomAuthenticationProvider(userDetailService,passwordEncoder());
        return customAuthenticationProvider;
    }
    

    @Bean
    public UserDetailsServiceAnonymousAuthenticationFilter anonymousAuthenticationFilter() {
        UserDetailsServiceAnonymousAuthenticationFilter anonymousAuthenticationFilter = new UserDetailsServiceAnonymousAuthenticationFilter(userDetailService);
        return anonymousAuthenticationFilter;
    }
    /*
    @Bean
    public SwitchUserFilter switchUserFilter() {
        SwitchUserFilter switchUserFilter = new SwitchUserFilter();
        switchUserFilter.setUserDetailsService(userDetailService);
        switchUserFilter.setTargetUrl("/");
        switchUserFilter.setSwitchUserUrl("/switchuserto");
        switchUserFilter.setUsernameParameter("username");
        switchUserFilter.setExitUserUrl("/switchuserlogout");
        return switchUserFilter;
    }*/

    @Bean
    public MDCUsernameInsertingFilter mdcUsernameInsertingFilter() {
        MDCUsernameInsertingFilter mdcUsernameInsertingFilter = new MDCUsernameInsertingFilter();
        return mdcUsernameInsertingFilter;
    }
    
    @Bean
    public SpringDataTokenRepositoryImpl springDataTokenRepository() {
        SpringDataTokenRepositoryImpl springDataTokenRepository = new SpringDataTokenRepositoryImpl();
        return springDataTokenRepository;
    }

    @Bean
    public RememberMeAuthenticationProvider rememberMeAuthenticationProvider() {
        RememberMeAuthenticationProvider rememberMeAuthenticationProvider = new RememberMeAuthenticationProvider(REMEMBER_ME_KEY);
        return rememberMeAuthenticationProvider;
    }

    @Bean
    public CustomWebSecurityExpressionHandler webSecurityExpressionHandler() {
        CustomWebSecurityExpressionHandler customWebSecurityExpressionHandler = new CustomWebSecurityExpressionHandler();
        return customWebSecurityExpressionHandler;
    }
	
}
